package com.xuecheng.content.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xuecheng.api.content.model.TeachplanDTO;
import com.xuecheng.api.system.model.dto.CourseCategoryDTO;
import com.xuecheng.common.domain.response.RestResponse;
import com.xuecheng.common.enums.common.CommonEnum;
import com.xuecheng.common.enums.content.CourseAuditEnum;
import com.xuecheng.common.enums.content.CourseModeEnum;
import com.xuecheng.common.exception.ExceptionCast;
import com.xuecheng.common.util.JsonUtil;
import com.xuecheng.content.common.CoursePubTemplateKey;
import com.xuecheng.content.common.constant.ContentErrorCode;
import com.xuecheng.content.convert.CourseBaseConvert;
import com.xuecheng.content.convert.CoursePubConvert;
import com.xuecheng.content.entity.*;
import com.xuecheng.content.mapper.CoursePubMapper;
import com.xuecheng.content.service.*;
import com.xuecheng.openfeign.SystemApiAgent;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 课程发布 服务实现类
 * </p>
 *
 * @author itcast
 */
@Slf4j
@Service
public class CoursePubServiceImpl extends ServiceImpl<CoursePubMapper, CoursePub> implements CoursePubService {

    @Autowired
    private CourseBaseService courseBase;//课程基础信息

    @Autowired
    private CourseMarketService courseMarket;//课程营销

    @Autowired
    private CourseTeacherService teacherService;//课程计划

    @Autowired
    private TeachplanService teachplanService;//课程教师

    @Autowired
    private SystemApiAgent stemApiAgent;//远程调用获取课程分类
    @Autowired
    private CoursePubMsgService coursePubMsgService;

    @Autowired
    private RabbitTemplate rabbitTemplate;


    @Value("${course.publish.exchange}")
    private String exchange;

    @Value("${course.publish.routingkey}")
    private String routingkey;

    /**
     * 课程预览
     *
     * @param courseBaseId
     * @param companId
     * @return Map 数据模型 Map
     * 业务分析
     * 1:课程基本信息的查询并保存至课程发布表
     */
    @Override
    @Transactional
    public Map<String, Object> previewCourse(Long courseBaseId, Long companId) {
        //判断关键数据
        if (ObjectUtils.isEmpty(courseBaseId) ||
                ObjectUtils.isEmpty(companId)) {
            ExceptionCast.cast(ContentErrorCode.E_120038);
        }
        //查询课程基本信息表
        CourseBase courseBase = this.courseBase.getById(courseBaseId);
        //判断基本信息表数据-->状态+删除+机构id
        if (ObjectUtils.isEmpty(courseBase)) {
            ExceptionCast.cast(ContentErrorCode.E_120030);
        }
        if (!(companId.equals(courseBase.getCompanyId()))) {
            ExceptionCast.cast(ContentErrorCode.E_120030);
        }
        if (courseBase.getStatus().equals(CommonEnum.DELETE_FLAG.getCodeInt())) {
            ExceptionCast.cast(ContentErrorCode.E_120029);
        }
        if (!(courseBase.getAuditStatus().equals(CourseAuditEnum.AUDIT_UNPAST_STATUS.getCode())) &&
                !(courseBase.getAuditStatus().equals(CourseAuditEnum.AUDIT_DISPAST_STATUS.getCode()))) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
//        //保存至可曾发布表
//        CoursePub coursePub = CoursePubConvert.INSTANCE.pub2course(courseBase);
//        boolean save = this.save(coursePub);
//        if (!save) {
//            ExceptionCast.cast(ContentErrorCode.E_120031);
//        }
        //查询可课程营销
        LambdaQueryWrapper<CourseMarket> marketQueryWrapper = new LambdaQueryWrapper<>();
        marketQueryWrapper.eq(CourseMarket::getCourseId, courseBaseId);
        CourseMarket courseMarketOne = courseMarket.getOne(marketQueryWrapper);
        if (ObjectUtils.isEmpty(courseMarketOne)) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        //

        //查询课程教师表
        LambdaQueryWrapper<CourseTeacher> teacherLambdaQueryWrapper = new LambdaQueryWrapper<>();
        teacherLambdaQueryWrapper.eq(CourseTeacher::getCourseId, courseBaseId);
        List<CourseTeacher> teacherServiceOne = teacherService.list(teacherLambdaQueryWrapper);
//        if (ObjectUtils.isEmpty(teacherServiceOne)) {
//            ExceptionCast.cast(ContentErrorCode.E_120013);
//        }

        //

        //查询课程
        //树形结构课程计划
        TeachplanDTO teachplanDTO1 = teachplanService.queryTeachplanList(courseBaseId, companId);

        //获取课程分类信息
        String mt = courseBase.getMt();
        String st = courseBase.getSt();
        //查询课程分类数据

        RestResponse<CourseCategoryDTO> mtResponse = stemApiAgent.getById(mt);
        if (!(mtResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(mtResponse.getCode(), mtResponse.getMsg());
        }

        RestResponse<CourseCategoryDTO> stResponse = stemApiAgent.getById(st);

        if (!(stResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(stResponse.getCode(), stResponse.getMsg());
        }

        CourseCategoryDTO mtEntity = mtResponse.getResult();
        CourseCategoryDTO stEntity = stResponse.getResult();

        //保存课程基本数据至课程发布表
        CoursePub coursePub = CoursePubConvert.INSTANCE.courseBase2coursePub(CourseBaseConvert.INSTANCE.entity2dto(courseBase));

        //保存营销数据至发布表
        String maket = JsonUtil.objectTojson(courseMarketOne);
        coursePub.setMarket(maket);
        coursePub.setCharge(courseMarketOne.getCharge());
        coursePub.setPrice(courseMarketOne.getPrice());

        //保存课程计划信息至发布表
        String teachplan = JsonUtil.objectTojson(teachplanDTO1);
        coursePub.setTeachplan(teachplan);

        //保存课程教师
        String tojson = JsonUtil.objectTojson(teacherServiceOne);
        coursePub.setTeachers(tojson);

        //保存课程分类
        coursePub.setMtName(mtEntity.getName());
        coursePub.setStName(stEntity.getName());

        //根据课程id与机构id查询发布表-->判断是新增还是修改
        LambdaQueryWrapper<CoursePub> pubLambdaQueryWrapper = new LambdaQueryWrapper<>();
        pubLambdaQueryWrapper.eq(CoursePub::getCourseId, courseBaseId);
        pubLambdaQueryWrapper.eq(CoursePub::getCompanyId, companId);
        CoursePub coursePub1 = this.getOne(pubLambdaQueryWrapper);
        coursePub.setCourseId(courseBaseId);
        if (ObjectUtils.isEmpty(coursePub1)) {
            //新增
            boolean save = this.save(coursePub);
            if (!save) {
                ExceptionCast.cast(ContentErrorCode.E_120031);
            }
        } else {
            coursePub.setId(coursePub1.getId());
            boolean b = this.updateById(coursePub);
            if (!b) {
                ExceptionCast.cast(ContentErrorCode.E_120031);
            }

            //修改
        }


//        String marketJsonString = JsonUtil.objectTojson(courseMarket);

        // 1.构建数据模型对象
        HashMap<String, Object> dataMap = new HashMap<>();

        // 2.构建coursePub
        dataMap.put(CoursePubTemplateKey.COURSEPUB, coursePub);

        // 3.构建courseMarket
        String marketJsonString = coursePub.getMarket();
        CourseMarket courseMarket = JsonUtil.jsonToObject(marketJsonString, CourseMarket.class);

        dataMap.put(CoursePubTemplateKey.COURSEMARKET, courseMarket);

        // 4.构建课程计划
        String teachplanJsonString = coursePub.getTeachplan();
        TeachplanDTO teachplanDTO = JsonUtil.jsonToObject(teachplanJsonString, TeachplanDTO.class);
        dataMap.put(CoursePubTemplateKey.TEACHPLANNODE, teachplanDTO);

        // 5.构建课程模式
        CourseModeEnum[] values = CourseModeEnum.values();
        dataMap.put(CoursePubTemplateKey.COURSETEACHMODEENUMS, values);

        return dataMap;
    }

    /**
     * @param courseId
     * @param companyId
     * @return void
     * @Description 课程发布
     * @Date 2021/12/19 11:12
     * @Param [courseId, companyId] 课程id个教育机构id
     * 业务分析
     * 开启事务
     * 关键数据
     * courseId companyId
     * 业务数据
     * 基本课程信息
     * 是否有数据.是否删除.是否审核通过
     * 课程营销数据
     * 课程计划信息
     * 课程教师信息
     * 课程分类信息
     */
    @Override
    public void publish(Long courseId, Long companyId) {
        //关键数据
        if (ObjectUtils.isEmpty(courseId) ||
                ObjectUtils.isEmpty(companyId)) {
            ExceptionCast.cast(ContentErrorCode.E_120030);
        }

        //获取课程基本信息
        CourseBase courseBase1 = courseBase.getById(courseId);
        if (ObjectUtils.isEmpty(courseBase1)) {
            ExceptionCast.cast(ContentErrorCode.E_120013);
        }
        if (!(courseBase1.getStatus().equals(CommonEnum.USING_FLAG.getCodeInt()))) {
            ExceptionCast.cast(ContentErrorCode.E_120029);
        }
        if (!(courseBase1.getAuditStatus().equals(CourseAuditEnum.AUDIT_PASTED_STATUS.getCode()))) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }
        if (!(courseBase1.getCompanyId().equals(companyId))) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }


        //课程营销表
        LambdaQueryWrapper<CourseMarket> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(CourseMarket::getCourseId, courseId);
        CourseMarket courseMarketOne = courseMarket.getOne(queryWrapper);
        if (ObjectUtils.isEmpty(courseMarketOne)) {
            ExceptionCast.cast(ContentErrorCode.E_120015);
        }

        //查询课程教师表
        LambdaQueryWrapper<CourseTeacher> teacherLambdaQueryWrapper = new LambdaQueryWrapper<>();
        teacherLambdaQueryWrapper.eq(CourseTeacher::getCourseId, courseId);
        List<CourseTeacher> teacherServiceOne = teacherService.list(teacherLambdaQueryWrapper);
//        if (ObjectUtils.isEmpty(teacherServiceOne)) {
//            ExceptionCast.cast(ContentErrorCode.E_120013);
//        }

        //查询课程
        //树形结构课程计划
        TeachplanDTO teachplanDTO1 = teachplanService.queryTeachplanList(courseId, companyId);

        //获取课程分类信息
        String mt = courseBase1.getMt();
        String st = courseBase1.getSt();
        //查询课程分类数据

        RestResponse<CourseCategoryDTO> mtResponse = stemApiAgent.getById(mt);
        if (!(mtResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(mtResponse.getCode(), mtResponse.getMsg());
        }

        RestResponse<CourseCategoryDTO> stResponse = stemApiAgent.getById(st);

        if (!(stResponse.isSuccessful())) {
            ExceptionCast.castWithCodeAndDesc(stResponse.getCode(), stResponse.getMsg());
        }
        CourseCategoryDTO mtEntity = mtResponse.getResult();
        CourseCategoryDTO stEntity = stResponse.getResult();

        //保存课程基本数据至课程发布表
        CoursePub coursePub = CoursePubConvert.INSTANCE.courseBase2coursePub(CourseBaseConvert.INSTANCE.entity2dto(courseBase1));

        //保存营销数据至发布表
        String maket = JsonUtil.objectTojson(courseMarketOne);
        coursePub.setMarket(maket);
        coursePub.setCharge(courseMarketOne.getCharge());
        coursePub.setPrice(courseMarketOne.getPrice());

        //保存课程计划信息至发布表
        String teachplan = JsonUtil.objectTojson(teachplanDTO1);
        coursePub.setTeachplan(teachplan);

        //保存课程教师
        String tojson = JsonUtil.objectTojson(teacherServiceOne);
        coursePub.setTeachers(tojson);

        //保存课程分类
        coursePub.setMtName(mtEntity.getName());
        coursePub.setStName(stEntity.getName());


        //根据课程id与机构id查询发布表-->判断是新增还是修改
        LambdaQueryWrapper<CoursePub> pubLambdaQueryWrapper = new LambdaQueryWrapper<>();
        pubLambdaQueryWrapper.eq(CoursePub::getCourseId, courseId);
        pubLambdaQueryWrapper.eq(CoursePub::getCompanyId, companyId);
        CoursePub coursePub1 = this.getOne(pubLambdaQueryWrapper);


        //保存或者修改
        coursePub.setCourseId(courseId);
        if (ObjectUtils.isEmpty(coursePub1)) {
            //新增
            boolean save = this.save(coursePub);
            if (!save) {
                ExceptionCast.cast(ContentErrorCode.E_120031);
            }
        } else {
            //修改
            coursePub.setId(coursePub1.getId());
            boolean b = this.updateById(coursePub);
            if (!b) {
                ExceptionCast.cast(ContentErrorCode.E_120031);
            }
        }


        //保存数据至course_pub_msg
        CoursePubMsg coursePubMsg = new CoursePubMsg();
        coursePubMsg.setCourseId(courseId);
        coursePubMsg.setPubStatus(CommonEnum.DELETE_FLAG.getCodeInt());
        coursePubMsg.setCompanyId(companyId);
        coursePubMsg.setPubName(courseBase1.getName());
        coursePubMsg.setPubId(coursePub.getId());
        //根据课程id查询是否有过发布信息
        LambdaQueryWrapper<CoursePubMsg> lambdaQueryWrapper = new LambdaQueryWrapper<>();
        lambdaQueryWrapper.eq(CoursePubMsg::getCourseId, courseId);
        lambdaQueryWrapper.eq(CoursePubMsg::getCompanyId, companyId);
        CoursePubMsg msgServiceOne = coursePubMsgService.getOne(lambdaQueryWrapper);
        if (ObjectUtils.isEmpty(msgServiceOne)) {
            //没有则新增发布信息w
            boolean save = coursePubMsgService.save(coursePubMsg);
            if (!save) {
                ExceptionCast.cast(ContentErrorCode.E_120031);
            }
        }
        //設置mq的ack通知
        CorrelationData correlationData = new CorrelationData(courseId.toString());

        //
        correlationData.getFuture().addCallback(
                /* 交互机响应成功的回调方法 */
                confirm -> {
                    // 交互机响应成功
                    if (confirm.isAck()) {
                        // 修改课程基本信息审核状态和发布消息表的状态
                        execChangeStatusData(new Long(correlationData.getId()));
                    }
                },
                /* 交互机响应失败的回调方法 */
                throwable -> {
                    log.error("课程发布消息通知失败,courseId:{},exception:{}", courseId, throwable.getMessage());
                }
        );
        String msgJsonString = JsonUtil.objectTojson(coursePubMsg);

        rabbitTemplate.convertAndSend(exchange, routingkey, msgJsonString, correlationData);
    }

    //消息发送成功成功后回调的方法
    private void execChangeStatusData(Long courseId) {
        //更改课程基本信息表
        LambdaUpdateWrapper<CourseBase> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(CourseBase::getId, courseId);
        wrapper.set(CourseBase::getChangeDate, LocalDateTime.now());
        wrapper.set(CourseBase::getAuditStatus, CourseAuditEnum.AUDIT_PUBLISHED_STATUS.getCode());
        boolean update = courseBase.update(wrapper);
        if (!update) {
            ExceptionCast.cast(ContentErrorCode.E_120031);
        }

        //修改课程发布表
        LambdaUpdateWrapper<CoursePubMsg> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        lambdaUpdateWrapper.eq(CoursePubMsg::getCourseId, courseId);
        lambdaUpdateWrapper.set(CoursePubMsg::getPubStatus, CommonEnum.USING_FLAG.getCodeInt());
        boolean b = coursePubMsgService.update(lambdaUpdateWrapper);
        if (!b) {
            ExceptionCast.cast(ContentErrorCode.E_120031);
        }

    }
}
